package com.jc.subject.domin.service.impl;

import com.alibaba.fastjson.JSON;
import com.jc.subject.common.entity.PageResult;
import com.jc.subject.common.enums.IsDeletedFlagEnum;
import com.jc.subject.domin.convert.SubjectInfoConverter;
import com.jc.subject.domin.entity.SubjectInfoBO;
import com.jc.subject.domin.entity.SubjectOptionBO;
import com.jc.subject.domin.handler.subject.SubjectTypeFactory;
import com.jc.subject.domin.handler.subject.SubjectTypeHandler;
import com.jc.subject.domin.service.SubjectInfoDomainService;
import com.jc.subject.infra.basic.entity.SubjectInfo;
import com.jc.subject.infra.basic.entity.SubjectLabel;
import com.jc.subject.infra.basic.entity.SubjectMapping;
import com.jc.subject.infra.basic.service.SubjectInfoService;
import com.jc.subject.infra.basic.service.SubjectLabelService;
import com.jc.subject.infra.basic.service.SubjectMappingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.security.auth.Subject;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author: ASL_ly
 * @Package: com.jc.subject.domin.service.impl
 * @Project: jc-club
 * @Date: 2024/10/23  19:35
 */
@Service
@Slf4j
public class SubjectInfoDomainServiceImpl implements SubjectInfoDomainService {

    @Resource
    private SubjectInfoService subjectInfoService;
    @Resource
    private SubjectTypeFactory subjectTypeFactory;
    @Resource
    private SubjectMappingService subjectMappingService;
    @Resource
    private SubjectLabelService subjectLabelService;


    /**
     * 新增题目
     * @param subjectInfoBO
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SubjectInfoBO subjectInfoBO) {
        if (log.isInfoEnabled()) {
            log.info("SubjectController.add.bo:{}", JSON.toJSONString(subjectInfoBO));
        }
        SubjectInfo subjectInfo = SubjectInfoConverter
                .INSTANCE.subjectBOToInfo(subjectInfoBO);
        //插入总题目表中
        subjectInfo.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.code);
        subjectInfoService.insert(subjectInfo);
        subjectInfoBO.setId(subjectInfo.getId());
        //插入各类题目分表中（利用策略+工厂设计模式实现）
        SubjectTypeHandler handler = subjectTypeFactory.getHandler(subjectInfo.getSubjectType());
        handler.add(subjectInfoBO);

        //插入分类，标签，题目关系表
        List<Long> categoryIdList = subjectInfoBO.getCategoryIds();
        List<Long> labelIdList = subjectInfoBO.getLabelIds();
        List<SubjectMapping> subjectMappingList = new LinkedList<>();
        categoryIdList.forEach(categoryId ->{
            labelIdList.forEach(labelId ->{
                SubjectMapping subjectMapping = SubjectMapping.builder()
                        .subjectId(subjectInfo.getId())
                        .categoryId(categoryId)
                        .labelId(labelId)
                        .isDeleted(IsDeletedFlagEnum.UN_DELETED.code)
                        .build();
                subjectMappingList.add(subjectMapping);
            });
        });
        subjectMappingService.BacthInsert(subjectMappingList);

    }

    /**
     * 查询题目列表
     * @param subjectInfoBO
     * @return
     */
    @Override
    public PageResult<SubjectInfoBO> getSubjectPage(SubjectInfoBO subjectInfoBO) {
        if (log.isInfoEnabled()) {
            log.info("SubjectController.getSubjectPage.bo:{}", JSON.toJSONString(subjectInfoBO));
        }
        SubjectInfo subjectInfo = SubjectInfoConverter
                .INSTANCE.subjectBOToInfo(subjectInfoBO);
        PageResult<SubjectInfoBO> boPageResult = new PageResult<>();
        boPageResult.setPageNo(subjectInfoBO.getPageNo());
        boPageResult.setPageSize(subjectInfoBO.getPageSize());
        //开始行
        Integer start = (subjectInfoBO.getPageNo() -1)*subjectInfoBO.getPageSize();
        //查询总题目数
        Integer count = subjectInfoService.countByCondition(subjectInfo, subjectInfoBO.getCategoryId()
                ,subjectInfoBO.getLabelId());
        if(count == 0){
            return boPageResult;
        }
        //查询题目列表
        List<SubjectInfo> subjectInfoList = subjectInfoService.queryPage(subjectInfo, subjectInfoBO.getCategoryId()
                ,subjectInfoBO.getLabelId(),start,subjectInfoBO.getPageSize());
        List<SubjectInfoBO> subjectInfoBOList = SubjectInfoConverter
                .INSTANCE.subjectInfoToBOList(subjectInfoList);
        boPageResult.setRecords(subjectInfoBOList);
        boPageResult.setTotal(count);
        return boPageResult;

    }

    /**
     * 查询题目信息
     * @param subjectInfoBO
     * @return
     */
    @Override
    public SubjectInfoBO querySubjectInfo(SubjectInfoBO subjectInfoBO) {
        if (log.isInfoEnabled()) {
            log.info("SubjectController.querySubjectInfo.bo:{}", JSON.toJSONString(subjectInfoBO));
        }
        //1.查询主表信息
        SubjectInfo subjectInfo = subjectInfoService.queryById(subjectInfoBO.getId());

        //2.查询各类题目分表（利用策略+工厂设计模式实现）
        Integer subjectType = subjectInfo.getSubjectType();
        SubjectTypeHandler handler = subjectTypeFactory.getHandler(subjectType);
        SubjectOptionBO subjectOptionBO = handler.query(subjectInfoBO.getId());
        SubjectInfoBO boResult = SubjectInfoConverter
                .INSTANCE.subjectInfoToBO(subjectInfo, subjectOptionBO);

        //3.查询该题目的所有标签名
        SubjectMapping subjectMapping = SubjectMapping.builder()
                .subjectId(subjectInfoBO.getId())
                .isDeleted(IsDeletedFlagEnum.UN_DELETED.code)
                .build();
        //先获取包含该题目的所有标签id
        List<SubjectMapping> mappingList = subjectMappingService.queryLabelIdList(subjectMapping);
        List<Long> labelIdList = mappingList.stream().map(SubjectMapping::getLabelId).collect(Collectors.toList());
        //再通过标签id查询对应的标签名
        List<SubjectLabel> subjectLabelList = subjectLabelService.batchQuerryById(labelIdList);
        List<String> labelNameList = subjectLabelList.stream().map(SubjectLabel::getLabelName).collect(Collectors.toList());
        boResult.setLabelName(labelNameList);
        return boResult;
    }


}
